package com.FFmpeg;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileNameUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.*;

/**
 * @author 航
 * @date 2024/07/08 15:57
 * ffmpeg命令参考：https://www.cnblogs.com/lixingwu/p/13252846.html
 **/
public class RunCommandInDirectory {

    public static final int THREAD_POOL_SIZE = 1; // 根据你的需要设置线程池大小

    private static final Logger logger = LogManager.getLogger(RunCommandInDirectory.class);
    private String outPath;

    public File handleFileName(File file) {
        // 获得当前文件名，并将文件名中的空格删除，最后重命名
        String fileName = FileUtil.mainName(file);
        fileName = fileName.replaceAll(" ", "");
        fileName = fileName.replaceAll("@", "");
        File newFile = new File(file.getParent(), fileName + "." + FileUtil.extName(file));
        return file.renameTo(newFile) ? newFile : file;
    }

    public void getAss(File file) {
        file = handleFileName(file);
        String command = "ffmpeg -i " + file.getPath() + " -map 0:s:0 -c:s copy -y " + FileUtil.mainName(file) + ".ass";
        try {
            // 执行命令
            Process process = Runtime.getRuntime().exec(command);
            // 读取命令行输出
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                logger.info("getAss:{}-->{}", Thread.currentThread().getName(), line);
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }

    /**
     * mkv转mp4不用单独写个方法的。
     * 这个方法主要是mkv转mp4时，要加入一个字幕文件，
     * 所以单独加个方法处理。
     *
     * @param sourceFile
     * @param subtitleFile
     */
    public void mkvToMp4(File sourceFile, File subtitleFile) {
        // 输出路径
        String outPath = sourceFile.getPath() + ".mp4";
        /**
         * 傻逼参数
         * ass=？
         * 就后面这个问号，不能是路径，只能是单个文件
         * 什么意思呢？就是反斜杠用不了
         * 源路径：E:\abc\01.ass
         * 直接输入路径就变成了 abc01.ass
         * 这不就找不到嘛
         * 之后再看看有没有更好的方法解决，先这样了
         */
        String command = "ffmpeg -i " + sourceFile.getPath() + " -vf \"ass=" + subtitleFile.getName() + "\" -c:v libx264 -preset veryfast -crf 23 -c:a copy " + outPath;
        try {
            Process process = Runtime.getRuntime().exec(command);
            // 读取命令行输出
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                logger.info("mkvToMp4:{}-->{}", Thread.currentThread().getName(), line);
            }
        } catch (IOException e) {
            logger.error(e.getMessage());
        }
    }

    /**
     * 删除视频第一秒
     *
     * @param path     文件路径（parentPath）
     * @param fileName 文件名
     * @throws Exception 抛异常
     */
    public void deleteFirstSecond(String path, String fileName) throws Exception {
        // 视频文件路径
        String videoFilePath = path + "\\" + fileName;
        // 目标路径
        // 如果统一格式的话，就在后面加上就行
        String outPath = path + "\\" + "new_" + fileName;
        // FFmpeg 截取命令
        // 命令参考：ffmpeg -i [输入文件] -ss [开始位置] -to [结束位置] -acodec [编码器] -y [输出文件]
        // -c:a copy 表示音频直接复制过来，跳过编码
        // -c:v copy 表示视频直接复制，跳过重新编码
        // + " -c:v copy -c:a copy -y " 表示音频和视频全部跳过编码
        // 经过测试，如果视频不进行重新编码，会在开头造成混乱。本来想截断掉第一秒，可是前十秒都被截断了
        String command = "ffmpeg -i " + videoFilePath + " -ss 00:00:01 -to " + new VideoInfo().findDuration(path, fileName) + " -y " + outPath;

        try {
            // 执行命令
            Process process = Runtime.getRuntime().exec(command);
            // 读取命令行输出
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                logger.info("deleteFirstSecond:{}-->{}", Thread.currentThread().getName(), line);
            }
            // process.waitFor(5, TimeUnit.SECONDS);  // 等待进程结束
            // 等待进程结束
            // int exitCode = process.waitFor();
            //System.out.println("Process exited with code: " + exitCode);
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }

    /**
     * 只转视频格式，并重命名
     */
    public void convertFormat(String path, String fileName, String outFormat) throws Exception {
        // 视频文件路径
        String videoFilePath = path + "\\" + fileName;
        // 目标路径
        String outPath = path + "\\" + "new_" + FileNameUtil.getPrefix(fileName) + "." + outFormat;
        String command = "ffmpeg -i "
                + videoFilePath
                + " "
                + outPath;
        try {
            // 执行命令
            Process process = Runtime.getRuntime().exec(command);
            // 读取命令行输出
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                logger.info("convertFormat:{}-->{}", Thread.currentThread().getName(), line);
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }
}
